package com.oracle.aspect;

import com.alibaba.fastjson.JSONObject;
import com.oracle.annotation.Action;
import com.oracle.log.service.api.LogServiceApi;
import com.oracle.pojo.Admins;
import com.oracle.pojo.Logs;
import com.oracle.shiro.Principal;
import com.oracle.vo.ResultEntity;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import java.util.Date;


//定义切面类
@Aspect
//@Component
public class LogAspect {


    public void initMethod(){
        System.out.println("初始化方法。。。。。");
    }

    @Autowired(required = false)
    private RabbitTemplate rabbitTemplate;
    @Value("${log_exchange}")
    private String log_exchange;
    @Value("${log_queue}")
    private String log_queue;
    @Value("${log_bindKey}")
    private String log_bindKey;

    //定义环绕增强方法，定义切入点表达式
    @Around("execution (* com.oracle.controller.*.*(..))")
    public Object logAdminMethod(ProceedingJoinPoint pjp){
        Object targetObj = null;
        //获取执行目标的方法名
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        String methodName = methodSignature.getName();
        //获取执行的类名
        String className = pjp.getTarget().getClass().getSimpleName();
        //拼接获取执行的方法全名
        String classAndMethodName = className+"."+methodName;
        //判断当前执行方法是否是日志方法，如果是忽略不进行日志记录，或者是common方法
        if (className.equals("LogController")||className.equals("CommonController")){
            try {
                targetObj = pjp.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return targetObj;
        }
        //不是的话，进行 日志的记录保存操作
        Logs logs = new Logs();
        //获取当前登录的管理员信息
        Principal principal = (Principal) SecurityUtils.getSubject().getPrincipal();
        if (principal != null){
            //当前用户
            logs.setAdmin(principal.getLoginName());
        }
        //当前执行方法
        logs.setExecutemethod(classAndMethodName);
        //当前执行参数
        if (pjp.getArgs().length>0){
            //JSONObject.toJSONString(pjp.getArgs())
            logs.setExecuteargs(null);
        }
        //方法执行所耗时间
            //获取开始的时间的毫秒值
        Long beginTime = System.currentTimeMillis();
        //执行方法
        try {
            targetObj = pjp.proceed();
            //记录返回值
            logs.setExecuteresult("success");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            logs.setExecuteresult(throwable.getMessage());
        }
            //结束时间
        Long endTime = System.currentTimeMillis();
        //计算赋值
        logs.setExecutetime(((float) (endTime-beginTime))/1000);
        //查看当前执行的方法是否有注解
        if (methodSignature.getMethod().isAnnotationPresent(Action.class)){
            //获取注解
            Action action = methodSignature.getMethod().getAnnotation(Action.class);
            //调用方法获取当前注解是什么类型
            logs.setExecutetype(this.analysisMethodType(action));
        }
        //创建时间
        logs.setCreatedate(new Date());
//        //执行保存日志信息
//        ResultEntity resultEntity = this.logServiceApi.addLogs(logs);
        //把日志添加消息丢给RabbitMQ处理
        this.rabbitTemplate.convertAndSend(this.log_exchange,this.log_bindKey,logs);
        return targetObj;
    }

    /**
     * 分析当前执行方法的注解是什么类型的
     * @param action
     * @return
     */
    private String analysisMethodType(Action action) {
        switch (action.value()){
            case ADD:
                return "添加类型";
            case DELETE:
                return "删除类型";
            case UPDATE:
                return "修改类型";
            case QUERY:
                return "查询类型";
            case PAGE_JUMPS:
                return "页面跳转类型";
            default:
                return "未定义类型";
        }
    }


}
